﻿using IService;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Model;
using Newtonsoft.Json;
using StackExchange.Redis;

namespace WMS.Controllers
{
    public class StockUpOrderController : Controller
    {
        // 新增：Redis连接实例
        private readonly IDatabase _redisDb;
        private readonly IDictService _dictService;
        private readonly IOmPurchaseOrderService _iopos;
        private readonly ISysAttachmentService _attachmentService;
        private readonly IWebHostEnvironment _env;  // 用于获取web根路径
        private readonly ILogger<StockUpOrderController> _logger; // 日志实例

        public StockUpOrderController(IDictService dictService, IOmPurchaseOrderService iopos,
                                      ISysAttachmentService attachmentService, IWebHostEnvironment env,
                                      ILogger<StockUpOrderController> logger,
                                      IConnectionMultiplexer redisMultiplexer) // 新增Redis连接参数)
        {
            _dictService = dictService; // 依赖注入公共组件的服务
            _iopos = iopos;
            _attachmentService = attachmentService;
            _env = env;
            _logger = logger;
            _redisDb = redisMultiplexer.GetDatabase();
        }

        //进货订单主界面
        public async Task<IActionResult> Index()
        {
            // 调用公共组件方法获取性别字典数据
            //(需要哪个数据字典，参数即为对应的wms_dict_type表中的code列的值)
            //(例如需要性别数据，就在wms_dict_type中找到用户性别列，根据对应的code列写"sys_sex")
            var dictType = await _dictService.GetDictTypeAsync("sys_job_type");
            if (dictType != null)
            {
                var sexList = await _dictService.GetDictDataListAsync(dictType.DictTypeId);
                ViewBag.SexList = sexList;
            }
            var dictTypeForStockIn = await _dictService.GetDictTypeAsync("sys_stockin_order_statu");
            if(dictTypeForStockIn != null)
            {
                var stockInStatusList = await _dictService.GetDictDataListAsync(dictTypeForStockIn.DictTypeId);
                ViewBag.StockInStatusList = stockInStatusList;
            }
            return View();
        }

        //进货订单新增界面
        public IActionResult AddIndex()
        {
            return View();
        }

        //进货订单修改界面
        public async Task<IActionResult> UpdateIndex(long id)
        {
            // 1. 定义缓存键
            var cacheKey = $"StockUpOrder:Update:{id}";
            // 定义缓存过期时间
            var expiry = TimeSpan.FromMinutes(20);

            // 2. 尝试从Redis获取缓存数据
            var cachedData = await _redisDb.StringGetAsync(cacheKey);
            List<OmPurchaseOrderForUpdate> orderData = null; // 假设返回类型为该列表

            if (!cachedData.IsNull)
            {
                // 2.1 缓存存在：反序列化Redis中的JSON字符串为对象
                orderData = JsonConvert.DeserializeObject<List<OmPurchaseOrderForUpdate>>(cachedData);
                _logger.LogInformation($"订单ID:{id} 的修改数据从Redis缓存获取");
            }
            else
            {
                // 2.2 缓存不存在：查询数据库
                orderData = await _iopos.SelectOmPurchaseOrderByUpOrderId(id);
                if (orderData != null)
                {
                    // 序列化对象为JSON字符串，写入Redis并设置过期时间
                    var jsonData = JsonConvert.SerializeObject(orderData);
                    await _redisDb.StringSetAsync(cacheKey, jsonData, expiry);
                    _logger.LogInformation($"订单ID:{id} 的修改数据查询数据库后写入Redis缓存");
                }
                else
                {
                    _logger.LogWarning($"订单ID:{id} 未查询到数据，不写入缓存");
                }
            }

            // 3. 将数据传递到视图
            ViewData["OrderData"] = orderData;
            return View();
        }
        
        /// <summary>
        /// 进货订单修改
        /// </summary>
        /// <param name="omPurchaseOrderForUpdate"></param>
        /// <param name="details"></param>
        /// <param name="files"></param>
        /// <returns></returns>
        public async Task<IActionResult> UpdateOmPurOrderFunc(string omPurchaseOrderForUpdate,
                                                              string details=null,
                                                              List<IFormFile> files= null)
        {
            return View();
        }

        /// <summary>
        /// 获取全部进货订单信息
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> GetAllOmPurchaseOrder()
        {
            var result = await _iopos.GetAllOmPurchaseOrderAsync();
            return Json(result);
        }

        /// <summary>
        /// 获取组织机构信息用于下拉表格
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> GetOrgInfoForSelectTable()
        {
            var orgList = await _iopos.GetOrgInfoForSelectTable();
            var treeData = FormatOrgDataForTree(orgList);
            return Json(treeData);
        }

        /// <summary>
        /// 获取用户信息用于下拉框
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> GetUserInfoForSelectTable()
        {
            var result = await _iopos.GetUserInfoForSelectTable();
            return Json(result);
        }

        /// <summary>
        /// 获取供应商信息用于下拉框
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> GetSupplierInfoForSelectTable()
        {
            var result = await _iopos.GetSupplierInfoForSelectTable();
            return Json(result);
        }

        /// <summary>
        /// 获取全部商品信息用于新增进货订单
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> GetAllGoodsInfoForAddGoods()
        {
            var result = await _iopos.GetAllGoodsInfoForAddGoods();
            return Json(result);
        }

        [HttpPost]
        public async Task<IActionResult> UploadAttachment(List<IFormFile> files,
                                                         string createBy,
                                                         DateTime createTime,
                                                         string updateBy,
                                                         DateTime updateTime)
        {
            try
            {
                if (files == null || files.Count == 0)
                {
                    return Json(new { success = false, message = "未上传任何文件" });
                }

                // 1. 定义文件存储路径（wwwroot/attachments/yyyyMMdd）
                var uploadDir = Path.Combine(_env.WebRootPath, "attachments", DateTime.Now.ToString("yyyyMMdd"));
                if (!Directory.Exists(uploadDir))
                {
                    Directory.CreateDirectory(uploadDir);  // 不存在则创建目录
                }

                // 2. 处理每个文件并转换为DTO
                var attachmentList = new List<SysAttachmentDTO>();
                foreach (var file in files)
                {
                    // 生成唯一文件名（避免重复）
                    var uniqueFileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}";
                    var filePath = Path.Combine(uploadDir, uniqueFileName);

                    // 保存文件到服务器
                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        await file.CopyToAsync(stream);
                    }

                    // 构建DTO对象
                    attachmentList.Add(new SysAttachmentDTO
                    {
                        AttachmentCode = GenerateAttachmentCode(),  // 生成附件编号
                        AttachmentAddress = filePath.Replace(_env.WebRootPath, "/attachments"),  // 存储相对路径
                        CreateBy = createBy,
                        CreateTime = createTime,
                        UpdateBy = updateBy,
                        UpdateTime = updateTime
                    });
                }

                // 3. 调用服务层批量保存到数据库
                var result = await _attachmentService.UploadAttachment(attachmentList);
                if (result > 0)
                {
                    return Json(new
                    {
                        success = true,
                        message = $"成功上传{result}个文件",
                        data = attachmentList  // 返回保存的附件信息给前端
                    });
                }
                return Json(new { success = false, message = "文件信息保存失败" });
            }
            catch (Exception ex)
            {
                return Json(new { success = false, message = $"上传失败：{ex.Message}" });
            }
        }

        /// <summary>
        /// 进货订单新增（含附件上传补偿机制）
        /// </summary>
        /// <param name="files"></param>
        /// <param name="createBy"></param>
        /// <param name="createTime"></param>
        /// <param name="updateBy"></param>
        /// <param name="updateTime"></param>
        /// <param name="opof"></param>
        /// <param name="opodf"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [HttpPost]
        public async Task<IActionResult> AddOmPurchaseOrderInfo(
                                                                string opofStr,
                                                                string opodfStr = null,
                                                                List<IFormFile> files = null,
                                                                string createBy = null,
                                                                string updateBy = null)
        {
            var uploadedFilePaths = new List<string>();
            bool isSuccess = false;
            int? result = null;

            // 步骤1：基础非空验证（仅校验主表）
            if (string.IsNullOrEmpty(opofStr))
                return Json(new { success = false, message = "订单主表信息不能为空" });

            // 步骤2：JSON反序列化配置
            var settings = new JsonSerializerSettings
            {
                DateParseHandling = DateParseHandling.None,
                FloatParseHandling = FloatParseHandling.Decimal
            };

            // 步骤3：反序列化订单主表（先解析主表，获取状态判断是否为草稿）
            OmPurchaseOrderForAdd opof = null;
            try
            {
                opof = JsonConvert.DeserializeObject<OmPurchaseOrderForAdd>(opofStr, settings);
            }
            catch (Exception ex)
            {
                return Json(new { success = false, message = $"订单主表解析错误：{ex.Message}" });
            }
            if (opof == null)
                return Json(new { success = false, message = "订单主表信息解析失败" });

            // 关键：判断是否为草稿（假设草稿状态为 "0"）
            bool isDraft = opof.OrderStatus == "0";

            // 步骤4：处理订单明细（根据草稿状态决定是否强制校验）
            List<OmPurchaseOrderDetailForAdd> opodfList = new List<OmPurchaseOrderDetailForAdd>();
            if (!isDraft)
            {
                // 非草稿：强制校验明细非空
                if (string.IsNullOrEmpty(opodfStr))
                    return Json(new { success = false, message = "订单明细表信息不能为空" });

                var detailWrapper = new { Details = new List<OmPurchaseOrderDetailForAdd>() };
                try
                {
                    var temp = JsonConvert.DeserializeAnonymousType(opodfStr, detailWrapper, settings);
                    if (temp?.Details == null || temp.Details.Count == 0)
                        return Json(new { success = false, message = "订单明细为空或格式错误" });
                    opodfList = temp.Details;
                }
                catch (Exception ex)
                {
                    return Json(new { success = false, message = $"订单明细解析错误：{ex.Message}" });
                }
            }
            else
            {
                // 草稿状态：允许明细为空（opodfStr为空或解析后无数据）
                if (!string.IsNullOrEmpty(opodfStr))
                {
                    // 若传递了明细，则尝试解析（可选，草稿也可带明细）
                    var detailWrapper = new { Details = new List<OmPurchaseOrderDetailForAdd>() };
                    try
                    {
                        var temp = JsonConvert.DeserializeAnonymousType(opodfStr, detailWrapper, settings);
                        opodfList = temp?.Details ?? new List<OmPurchaseOrderDetailForAdd>();
                    }
                    catch (Exception ex)
                    {
                        return Json(new { success = false, message = $"订单明细解析错误：{ex.Message}" });
                    }
                }
                // 若opodfStr为空，opodfList保持空列表
            }

            try
            {
                #region 2. 上传文件并记录路径（仅当有附件时执行）
                var attachmentList = new List<SysAttachmentDTO>();
                string commonAttachmentCode = null;

                if (files != null && files.Count > 0)
                {
                    commonAttachmentCode = GenerateAttachmentCode();
                    var uploadDir = Path.Combine(_env.WebRootPath, "attachments", DateTime.Now.ToString("yyyyMMdd"));
                    if (!Directory.Exists(uploadDir))
                        Directory.CreateDirectory(uploadDir);

                    foreach (var file in files)
                    {
                        var uniqueFileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}";
                        var filePath = Path.Combine(uploadDir, uniqueFileName);

                        using (var stream = new FileStream(filePath, FileMode.Create))
                            await file.CopyToAsync(stream);

                        uploadedFilePaths.Add(filePath);
                        attachmentList.Add(new SysAttachmentDTO
                        {
                            AttachmentCode = commonAttachmentCode,
                            AttachmentAddress = filePath.Replace(_env.WebRootPath, "/attachments"),
                            CreateBy = createBy,
                            CreateTime = DateTime.Now,
                            UpdateBy = updateBy,
                            UpdateTime = DateTime.Now,
                        });
                    }

                    // 仅当有明细时，关联附件编号（草稿可能无明细，跳过）
                    foreach (var detail in opodfList)
                        detail.AttachmentCode = commonAttachmentCode;
                }
                else
                {
                    // 无附件时，明细的attachment_code设为“无”（仅当有明细时）
                    foreach (var detail in opodfList)
                        detail.AttachmentCode = "无";
                }
                #endregion

                #region 3. 执行数据库操作（传递明细和附件，DAL层会处理空明细）
                result = await _iopos.AddOmpurchaseOrderInfo(opof, opodfList, attachmentList);

                if (result == null || result == 0)
                    throw new Exception("数据库操作返回失败标识（0或null）");

                isSuccess = true;
                #endregion

                return Json(new { success = true, data = result, message = "操作成功" });
            }
            catch (Exception ex)
            {
                return Json(new { success = false, message = $"操作失败：{ex.Message}" });
            }
            finally
            {
                #region 4. 补偿逻辑（失败时删除已上传文件）
                if (!isSuccess && uploadedFilePaths.Count > 0)
                {
                    foreach (var filePath in uploadedFilePaths)
                    {
                        if (System.IO.File.Exists(filePath))
                        {
                            try
                            {
                                System.IO.File.Delete(filePath);
                                _logger.LogInformation($"补偿逻辑：已删除文件 {filePath}");
                            }
                            catch (Exception deleteEx)
                            {
                                _logger.LogError(deleteEx, $"补偿逻辑失败：无法删除文件 {filePath}");
                            }
                        }
                    }
                }
                #endregion
            }
        }


        /// <summary>
        /// 多条件查询进货订单
        /// </summary>
        /// <param name="sopows"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> SearchInfoBySmth([FromBody]SearchOmPurOrderWithSmth sopows)
        {
            var result = await _iopos.SearchOmPurOrderWithSmthFunc(sopows);
            return Json(result);
        }

        /// <summary>
        /// 跳转订单详情界面
        /// </summary>
        /// <param name="upOrderId"></param>
        /// <returns></returns>
        public async Task<IActionResult> DetailIndex(long upOrderId)
        {
            var result = await _iopos.CheckOmPurOrderDetailInfo(upOrderId);
            ViewData["OrderDetail"] = result;
            var dictTypeForStockIn = await _dictService.GetDictTypeAsync("sys_stockin_order_statu");
            if (dictTypeForStockIn != null)
            {
                var stockInStatusList = await _dictService.GetDictDataListAsync(dictTypeForStockIn.DictTypeId);
                ViewBag.StockInStatusList = stockInStatusList;
            }
            return View();
        }

        //[HttpPost]
        //public async Task<IActionResult> UpdateOmPurchaseOrderInfo(
        //                                                            string opofStr,
        //                                                            string opodfStr = null,
        //                                                            List<IFormFile> files = null,
        //                                                            string createBy = null,
        //                                                            string updateBy = null)
        //{

        //}


        public class ChangeOrderStatusRequest
        {
            public string Statu { get; set; }
            public long UpOrderId { get; set; }
            public long UpdateBy { get; set; }
        }

        /// <summary>
        /// 非审核修改进货订单状态
        /// </summary>
        /// <param name="statu"></param>
        /// <param name="upOrderId"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> ChangeOmPurOrderStatu([FromBody] ChangeOrderStatusRequest request)
        {
            // 从模型中获取参数
            var result = await _iopos.ChangeOmPurOrderStatu(
                request.Statu,
                request.UpOrderId,
                request.UpdateBy
            );
            return Json(result);
        }

        public class AuditOmPurOrderRequest
        {
            public long AuditorBy { get; set; }
            public string AuditorComment { get; set; }
            public string Statu { get; set; }
            public long UpOrderId { get; set; }
        }

        /// <summary>
        /// 审核进货订单
        /// </summary>
        /// <param name="auditorBy"></param>
        /// <param name="auditorComment"></param>
        /// <param name="statu"></param>
        /// <param name="upOrderId"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> AuditOmPurOrder([FromBody] AuditOmPurOrderRequest request)
        {
            // 从 request 中获取参数
            var result = await _iopos.AuditOmPurOrder(
                request.AuditorBy,
                request.AuditorComment,
                request.Statu,
                request.UpOrderId
            );
            return Json(result);
        }


        public class DeleteRequest
        {
            public List<long> ids { get; set; }
            public long updateBy { get; set; }
        }
        /// <summary>
        /// 批量删除进货订单
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="updateBy"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> DeleteOmPurOrder([FromBody] DeleteRequest dr)
        {
            var result = await _iopos.DeleteOmPurOrder(dr.ids, dr.updateBy);
            return Json(result);
        }

        //辅助方法------------------------------------------------------------------------------------------

        /// <summary>
        /// 将组织架构数据格式化为树形结构
        /// </summary>
        /// <param name="orgList"></param>
        /// <returns></returns>
        [HttpPost]
        public List<object> FormatOrgDataForTree(List<SysOrganizationDTO> orgList)
        {
            // 先按父ID分组
            var groupByParent = orgList.GroupBy(o => o.ParentOrgId).ToDictionary(g => g.Key, g => g.ToList());

            // 递归构建树结构
            Func<long, List<object>> buildTree = null;
            buildTree = parentId =>
            {
                var result = new List<object>();
                if (groupByParent.TryGetValue(parentId, out var children))
                {
                    foreach (var child in children)
                    {
                        var node = new
                        {
                            id = child.OrgId,
                            label = child.OrgName,
                            children = buildTree(child.OrgId)
                        };
                        result.Add(node);
                    }
                }
                return result;
            };

            // 从父ID为0（根节点）开始构建
            return buildTree(0);
        }

        /// <summary>
        /// 生成附件编号（业务规则：ATT+日期+随机数）
        /// </summary>
        private string GenerateAttachmentCode()
        {
            return $"ATT_{DateTime.Now:yyyyMMdd}_{Guid.NewGuid().ToString("N").Substring(0, 6)}";
        }
    }
}
